package com.codi.api.controller.h5;

import com.codi.api.validation.TradeValidation;
import com.codi.base.cache.CacheUtil;
import com.codi.base.dao.plugin.page.PageView;
import com.codi.base.exception.BaseAppException;
import com.codi.base.exception.ExceptionHandler;
import com.codi.base.log.annotation.Loggable;
import com.codi.base.util.*;
import com.codi.base.web.RequestUtils;
import com.codi.bus.constant.FundConst;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.core.domain.User;
import com.codi.bus.core.domain.UserBank;
import com.codi.bus.core.resultModel.*;
import com.codi.bus.core.service.*;
import com.codi.bus.core.service.model.*;
import com.codi.bus.core.util.BaseResultUtil;
import com.codi.bus.core.vo.BuyVo;
import com.codi.bus.exception.BaseException;
import com.codi.bus.util.FundOperation;
import com.codi.bus.util.HtmlUtil;
import com.codi.fundData.domain.*;
import com.codi.message.constant.ErrorConst;
import com.codi.message.constant.ErrorConstant;
import com.codi.message.util.MessageUtil;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 因为涉及到重定向URL，更改成@Controller
 */
@Controller
@Slf4j
@RequestMapping("h5/fund")
public class H5FundController {

    @Resource(name = "fundDetailService")
    private FundDetailService fundDetailService;
    @Autowired
    private RedisTemplate<String, String> stringRedisTemplate;
    @Autowired
    private QueryService queryService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private UserService userService;
    @Resource(name = "tradeService")
    private TradeService tradeService;
    @Autowired
    private FundNetValueBackService fundNetValueBackService;
    @Autowired
    private PaperInfoService paperInfoService;
    @Autowired
    private TradeValidation tradeValidation;

    @Autowired
    private DividendApplyService dividendApplyQuery;

    @Resource(name = "bankService")
    private BankService bankService;

    @Resource(name = "fundInfoService")
    private FundInfoService fundInfoService;

    @Autowired
    private T0Service t0Service;
    @Autowired
    private ApplyRecordService applyRecordService;

    @Autowired
    private TradeOrderService tradeOrderService;
    /**
     * 查询基金概况
     *
     * @param fundCode
     * @return
     * @Author wzh
     */
    @GetMapping("overview")
    @ResponseBody
    @Loggable
    public BaseResult queryOverView(String fundCode) {
        BaseResult result = new BaseResult();
        result.setResult(fundDetailService.getFundOverView(fundCode));

        return result;
    }

    /**
     * 获取资产配置数据
     *
     * @param fundCode
     * @return
     * @Author wzh
     */
    @GetMapping("assetAllocation")
    @ResponseBody
    @Loggable
    public BaseResult getAssetAllocation(String fundCode) {
        FundAssetAllocationResult result = new FundAssetAllocationResult();
        SecurityProduct product;
        product = fundDetailService.getSecurityProduct(fundCode);

        if (product == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_FUND_NOT_EXIST);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_FUND_NOT_EXIST, fundCode));

            return result;
        }

        // 资产配置
        List<Integer> assetTypeCodes = new ArrayList<>(5);
        // 股票 、 债券 、银行存款、其他资产、 基金
        assetTypeCodes.add(FundConst.ASSET_TYPE_CODE_STOCK);
        assetTypeCodes.add(FundConst.ASSET_TYPE_CODE_BOND);
        assetTypeCodes.add(FundConst.ASSET_TYPE_CODE_BANK);
        assetTypeCodes.add(FundConst.ASSET_TYPE_CODE_OTHER);
        assetTypeCodes.add(FundConst.ASSET_TYPE_CODE_FUND);

        List<FundAssetAllocationModel> assetAllocations = fundDetailService.getFundAssetAllocation(
            product.getInnerCode(), assetTypeCodes);
        result.setAssetAllocations(assetAllocations);

        // 十大重仓
        List<FundPortifolio> portifolios = fundDetailService.getFundPortifolio(product.getInnerCode());
        result.setPortifolios(portifolios);

        // 行业分布
        List<FundInvestIndustryModel> industrys = fundDetailService.getFundInvestIndustry(product.getInnerCode());
        result.setIndustrys(industrys);

        result.setSuccess(true);

        return result;
    }

    /**
     * 基金详情-查询分红拆分数据
     *
     * @param fundCode
     * @return
     * @Author wzh
     */
    @GetMapping("dividendAndSharesSplit")
    @ResponseBody
    @Loggable
    public BaseResult getDividendAndSharesSplit(String fundCode) {
        FundDividendAndSharesSplitResult result = new FundDividendAndSharesSplitResult();
        result.setSuccess(false);

        SecurityProduct product;
        product = fundDetailService.getSecurityProduct(fundCode);

        if (product == null) {
            result.setErrorCode(ErrorConstant.ERROR_FUND_NOT_EXIST);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_FUND_NOT_EXIST, fundCode));

            return result;
        }

        FundDetail fundDetail = fundDetailService.getFundDetailByInnerCode(product.getInnerCode());
        if (EqualsUtil.equals(fundDetail.getFundTypeCode().intValue(), FundConst.FUND_TYPE_CODE_CURRENCY)) {
            result.setErrorCode(ErrorConstant.ERROR_FUND_CURRENCY_NO_SHARE);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_FUND_CURRENCY_NO_SHARE));

            return result;
        }


        Map<String, Object> param = new HashMap<String, Object>();

        PageView pageView = new PageView();
        pageView.setPageNow(1); // 页码
        pageView.setPageSize(50);

        param.put("pageView", pageView);
        param.put("innerCode", product.getInnerCode());
        param.put("ifDistributed", FundConst.FUND_DIVIDEND_DISTRIBUTE_YES);

        List<FundDividend> list = fundDetailService.getFundDividend(param);

        if (ListUtil.isNotEmpty(list)) {

            List<FundDividendModel> dividendList = new ArrayList<>(list.size());
            for (FundDividend dividend : list) {
                FundDividendModel obj = new FundDividendModel();

                if (dividend.getDividendRatioBeforeTax() != null) {
                    obj.setRatio(MoneyUtils.formatMoney(
                        dividend.getDividendRatioBeforeTax().divide(GlobalConstant.NUMBER_TEN), 4));
                }

                obj.setExecuteDate(dividend.getExecuteDate());
                obj.setExRightDate(dividend.getExRightDate());
                obj.setReDate(dividend.getReDate());
                dividendList.add(obj);
            }
            result.setDividendList(dividendList);
        }

        List<FundSharesSplit> shareList = fundDetailService.getFundSharesSplit(param);

        if (ListUtil.isNotEmpty(shareList)) {
            List<FundSharesSplitModel> sharesSplitList = new ArrayList<>(shareList.size());
            for (FundSharesSplit item : shareList) {
                FundSharesSplitModel obj = new FundSharesSplitModel();

                obj.setSplitDay(item.getSplitDay());
                if (item.getSplitRatio() != null) {
                    obj.setSplitRatio(MoneyUtils.formatMoney(item.getSplitRatio(), 4));
                }

                sharesSplitList.add(obj);
            }
            result.setSharesSplitList(sharesSplitList);
        }
        result.setSuccess(true);

        return result;
    }


    /**
     * 基金详情 查询基金经理信息
     *
     * @param managerCode
     * @return
     * @Author wzh
     */
    @GetMapping("manager")
    @ResponseBody
    @Loggable
    public BaseResult getFundManager(String managerCode) {
        FundManagerResult result = new FundManagerResult();
        Long personCode = Long.valueOf(managerCode);

        FundPersonInfo personInfo = fundDetailService.getFundPersonInfo(personCode);

        if (personInfo == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_FUND_MANAGER_NOT_EXIST);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_FUND_MANAGER_NOT_EXIST));

            return result;
        }

        result.setName(personInfo.getChineseName());
        result.setGender(personInfo.getGender());
        result.setBirthDate(personInfo.getBirthDate());
        // 1-博士后，2-博士，3-硕士，4-大学本科，5-大专
        result.setEducation(personInfo.getEducation());
        // 证券从业日期
        result.setPracticeDate(personInfo.getPracticeDate());
        // 证券从业经历
        result.setExperienceTime(MoneyUtils.formatMoney(personInfo.getExperienceTime(), 1));
        result.setProQualifi(personInfo.getProQualifi());// 从业资格
        result.setBackground(personInfo.getBackground());// 背景资料


        List<Map<String, Object>> fundPerfList = fundDetailService.getFundManagerPerformance(managerCode, null);

        if (ListUtil.isNotEmpty(fundPerfList)) {
            // 基金经理业绩
            List<FundManagerPerformanceModel> perfList = new ArrayList<>();
            for (Map<String, Object> map : fundPerfList) {
                FundManagerPerformanceModel perf = new FundManagerPerformanceModel();
                perf.setFundName(MapUtils.getStr(map, "ChiNameAbbr"));
                perf.setFundNameAbbr(MapUtils.getStr(map, "SecuAbbr"));
                perf.setAccessionDate(MapUtils.getDate(map, "AccessionDate"));
                perf.setDimissionDate(MapUtils.getDate(map, "DimissionDate"));
                perf.setPerformance(MoneyUtils.calcRateToFrontEnd(MapUtils.getBigDecimal(map, "Performance")));
                perf.setFundCode(MapUtils.getStr(map, "SecuCode"));
                perfList.add(perf);
            }

            log.info("查询基金经理业绩完成");
            result.setPerformance(perfList);
        }

        result.setSuccess(true);

        return result;
    }

    /**
     * 基金-详情 查询基金管理人信息
     *
     * @param investAdvisorCode
     * @return
     * @throws BaseAppException
     * @Author wzh
     */
    @GetMapping("investAdvisor")
    @ResponseBody
    @Loggable
    public BaseResult getInvestAdvisor(Integer investAdvisorCode) throws BaseAppException {
        FundInvestAdvisorResult result = new FundInvestAdvisorResult();

        FundInvestAdvisorOutline investAdvisor = fundDetailService.getFundInvestAdvisorOutline(investAdvisorCode);

        result.setBackground(HtmlUtil.convert2HTML(investAdvisor.getBackground()));

        List<Map<String, Object>> fundList = fundDetailService.getFundByInvestAdvisor(investAdvisorCode, 1, 10);

        if (ListUtil.isNotEmpty(fundList)) {

            List<String> fundCodeList = new ArrayList<>(fundList.size());

            for (Map<String, Object> map : fundList) {
                fundCodeList.add(MapUtils.getStr(map, "FundCode"));
            }

            List<FundPerformanceResult> performances = fundDetailService.getFundPerformanceByBatch(fundCodeList);
            if (ListUtil.isNotEmpty(performances)) {
                List<FundInvestAdvisorFundModel> funds = new ArrayList<>(performances.size());
                for (FundPerformanceResult performance : performances) {
                    FundInvestAdvisorFundModel model = new FundInvestAdvisorFundModel();
                    model.setFundCode(performance.getFundCode());
                    model.setFundName(performance.getChiNameAbbr());
                    model.setFundNameAbbr(performance.getSecuAbbr());
                    model.setFundType(performance.getFundType());
                    model.setFundTypeCode(performance.getFundTypeCode());
                    model.setRRInSingleYear(MoneyUtils.formatMoney(performance.getRRInSingleYear(), 2));
                    funds.add(model);
                }
                result.setFunds(funds);
            }
        }

        result.setSuccess(true);

        return result;
    }


    /**
     * 基金详情-查询相关公告列表
     *
     * @param fundCode
     * @param pageIndex
     * @param pageSize
     * @return
     * @throws BaseAppException
     */
    @GetMapping("announcements")
    @ResponseBody
    @Loggable
    public BaseResult queryAnnouncements(String fundCode, Integer pageIndex, Integer pageSize) throws BaseAppException {
        FundAnnouncementsResult result = new FundAnnouncementsResult();
        FundDetail fundDetail = fundDetailService.getFundDetail(fundCode);

        if (fundDetail == null) {
            ExceptionHandler.publish(ErrorConst.FUND_NOT_EXIST);
        }

        List<FundAnnouncement> list = fundDetailService.getFundAnnouncements(fundDetail.getInnerCode(), pageIndex,
            pageSize);

        result.setAnnouncements(list);
        result.setSuccess(true);

        return result;
    }

    /**
     * 基金详情-查询单个基金
     *
     * @param resId
     * @param resType
     * @return
     */
    @GetMapping("announcement")
    @ResponseBody
    @Loggable
    public BaseResult queryAnnouncement(Long resId, String resType) {
        log.debug("resId={},resType={}", resId, resType);

        FundAnnouncementResult result = null;
        result = fundDetailService.getFundAnnouncement(resId, resType);
        result.setSuccess(true);

        return result;
    }


    /**
     * 交易说明
     *
     * @param fundCode 基金代码
     * @return
     * @throws BaseAppException
     */
    @GetMapping("purchaseNotice")
    @ResponseBody
    @Loggable
    public BaseResult getFundBuyNotice(String fundCode) throws BaseAppException {

        FundBuyNoticeResult result = new FundBuyNoticeResult();
        SecurityProduct product = fundDetailService.getSecurityProduct(fundCode);

        if (product == null) {

            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_FUND_NOT_EXIST);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_FUND_NOT_EXIST, fundCode));

            return result;
        }

        // 最最低持有份额
        NewsModel newsModel = queryService.getRiskLevel(fundCode);
        result.setMinHold(MoneyUtils.formatMoney(newsModel.getMinShare(), 0));

        // 份额类型
        ShareTypeModel shareTypeModel = queryService.getShareType(fundCode);

        if (shareTypeModel == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND));

            return result;
        }

        result.setShareType(shareTypeModel.getShareType());// 份额类型：a,b

        TradeLimitModel tradeLimitModel = queryService.getTradeLimit(fundCode,
            GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY, shareTypeModel.getShareType(),
            GlobalConstant.CUST_TYPE_PERSONAL, GlobalConstant.CAPITAL_MODE_EPAY);
        // 最小申购
        if (tradeLimitModel != null) {
            result.setMinPurchase(MoneyUtils.formatMoney(tradeLimitModel.getMinValue(), 2));

            T0Model toModel = t0Service.queryT0Fund(false, fundCode);

            if (toModel != null) {
                List<TradeLimitModel> tradeLimitModels = toModel.getLimits();

                if (tradeLimitModels != null && tradeLimitModels.size() > 0) {
                    tradeLimitModel = tradeLimitModels.get(0);

                    if (tradeLimitModel != null) {
                        result.setMinPurchase(MoneyUtils.formatMoney(tradeLimitModel.getMinValue(), 2));
                    }
                }
            }
        }

        // 赎回时最小赎回份额
        tradeLimitModel = queryService.getTradeLimit(fundCode, GlobalConstant.FUND_BUSIN_CODE_APPLY_SELL,
            shareTypeModel.getShareType(), GlobalConstant.CUST_TYPE_PERSONAL, GlobalConstant.CAPITAL_MODE_EPAY);
        if (tradeLimitModel != null) {
            result.setMinRedeem(MoneyUtils.formatMoney(tradeLimitModel.getMinValue(), 2));
        }

        FundDetail fundDetail = fundDetailService.getFundDetail(fundCode);
        result.setFundType(fundDetail.getFundType());
        result.setFundTypeCode(fundDetail.getFundTypeCode());

        // 货基没有申购费率
        if (EqualsUtil.equals(fundDetail.getFundTypeCode().intValue(), FundConst.FUND_TYPE_CODE_CURRENCY)) {
            result.setSuccess(true);
            result.setErrorCode(ErrorConstant.ERROR_FUND_CURRENCY_NO_RATE);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_FUND_CURRENCY_NO_RATE));

            return result;
        }

        // 申购费率
        List<FundRate> applyRateList = queryService.queryFundRate(fundCode, FundOperation.Apply);

        // 申购费率折扣
        List<FundDiscountSetting> applyDiscountSettingList = queryService.queryFundDiscountSettings(fundCode,
            FundOperation.Apply);

        if (ListUtil.isNotEmpty(applyRateList)) {
            Collections.sort(applyRateList);// 排序

            List<FundPurchaseModel> fundPurchaseList = new ArrayList<>();
            for (int i = 0; i < applyRateList.size(); i++) {
                FundRate fundRate = applyRateList.get(i);
                // 排除机构户（大客户）
                if (EqualsUtil.equals(fundRate.getCust_type(), GlobalConstant.CUST_TYPE_ORGANIZATION)) {
                    continue;
                }
                FundPurchaseModel model = new FundPurchaseModel();

                // 份额为B的，不需要进行折扣
                if (EqualsUtil.equalsIgnoreCase(shareTypeModel.getShareType(), GlobalConstant.SHARE_TYPE_B)) {
                    model.setMinValue(fundRate.getMin_hold());
                    model.setMaxValue(fundRate.getMax_hold());
                    model.setFareRatio(MoneyUtils.calcRateToFrontEnd(fundRate.getRatio()));
                    fundPurchaseList.add(model);
                    continue;
                }

                model.setMinValue(fundRate.getMin_balance());
                model.setMaxValue(fundRate.getMax_balance());
                model.setFareRatio(MoneyUtils.calcRateToFrontEnd(fundRate.getRatio()));

                // 如果费率为0，则判断是否有【一笔交易多少钱】
                if (MoneyUtils.isZero(fundRate.getRatio())) {
                    model.setMinFare(MoneyUtils.parseRate(fundRate.getMin_fare(), 2));
                    model.setMaxFare(MoneyUtils.parseRate(fundRate.getMax_fare(), 2));
                    fundPurchaseList.add(model);
                    continue;
                }

                if (ListUtil.isNotEmpty(applyDiscountSettingList)) {
                    Collections.sort(applyDiscountSettingList); // 排序

                    List<FundDiscountModel> fundDiscountList = new ArrayList<>();

                    BigDecimal MIN = new BigDecimal(fundRate.getMin_balance());
                    BigDecimal MAX = new BigDecimal(fundRate.getMax_balance());

                    for (int j = 0; j < applyDiscountSettingList.size(); j++) {
                        FundDiscountSetting discountSetting = applyDiscountSettingList.get(j);

                        BigDecimal discountMin = new BigDecimal(discountSetting.getMin_bala());
                        BigDecimal discountMax = new BigDecimal(discountSetting.getMax_bala());
                        //
                        FundDiscountModel discountModel = new FundDiscountModel();

                        // minBalance=maxBalance=0 统一折扣
                        if (discountMin.compareTo(discountMax) == 0
                            && discountMin.compareTo(GlobalConstant.BIG_DECIMAL_0) == 0) {

                            discountModel.setMinBalanceValue(fundRate.getMin_balance());
                            discountModel.setMaxBalanceValue(fundRate.getMax_balance());
                            discountModel.setDiscount(discountSetting.getDiscount());

                            // 计算折扣后的费率
                            String ratioAfterDiscount = MoneyUtils.calcRate(fundRate.getRatio(),
                                discountSetting.getDiscount(), discountSetting.getMin_fare_ratio());
                            discountModel.setFareRatioAfterDiscount(ratioAfterDiscount);
                            discountModel.setMinFareRatio(MoneyUtils.calcRateToFrontEnd(discountSetting
                                .getMin_fare_ratio()));

                            fundDiscountList.add(discountModel);
                            continue;
                        }

                        int compare = MIN.compareTo(discountMin);
                        if (compare == 0 || compare == -1) {

                            compare = MAX.compareTo(discountMax);
                            discountModel.setMinBalanceValue(discountSetting.getMin_bala());
                            discountModel.setMaxBalanceValue(compare >= 0 ? discountSetting.getMax_bala() : fundRate
                                .getMax_balance());
                            discountModel.setDiscount(discountSetting.getDiscount());

                            // 计算折扣后的费率
                            String ratioAfterDiscount = MoneyUtils.calcRate(fundRate.getRatio(),
                                discountSetting.getDiscount(), discountSetting.getMin_fare_ratio());
                            discountModel.setFareRatioAfterDiscount(ratioAfterDiscount);
                            discountModel.setMinFareRatio(MoneyUtils.calcRateToFrontEnd(discountSetting
                                .getMin_fare_ratio()));

                            fundDiscountList.add(discountModel);
                        } else {
                            int compareMax = MAX.compareTo(discountMax);
                            int compareMinMax = MIN.compareTo(discountMax); // 范围最小值和折扣最大值

                            if (compareMinMax > 0) {
                                discountModel.setDiscount(discountSetting.getDiscount());

                                discountModel.setMinBalanceValue(fundRate.getMin_balance());
                                discountModel.setMaxBalanceValue(compareMax >= 0 ? discountSetting.getMax_bala()
                                    : fundRate.getMax_balance());

                                // 计算折扣后的费率
                                String ratioAfterDiscount = MoneyUtils.calcRate(fundRate.getRatio(),
                                    discountSetting.getDiscount(), discountSetting.getMin_fare_ratio());
                                discountModel.setFareRatioAfterDiscount(ratioAfterDiscount);
                                discountModel.setMinFareRatio(MoneyUtils.calcRateToFrontEnd(discountSetting
                                    .getMin_fare_ratio()));

                                fundDiscountList.add(discountModel);
                            }

                        }

                    }
                    model.setDiscountList(fundDiscountList);
                }

                fundPurchaseList.add(model);
            }
            result.setFundPurchaseList(fundPurchaseList);
        }

        // 赎回
        List<FundRate> exceedRateList = queryService.queryFundRate(fundCode, FundOperation.Exceed);
        List<FundDiscountSetting> redeemDiscountSettingList = queryService.queryFundDiscountSettings(fundCode,
            FundOperation.Exceed);


        if (ListUtil.isNotEmpty(exceedRateList)) {
            Collections.sort(exceedRateList, new Comparator<FundRate>() {
                @Override
                public int compare(FundRate o1, FundRate o2) {
                    String min = "0", max = "0";
                    if (StringUtil.isNotEmpty(o1.getMin_hold())) {
                        min = o1.getMin_hold();
                    }
                    if (StringUtil.isNotEmpty(o2.getMax_hold())) {
                        max = o2.getMax_hold();
                    }

                    BigDecimal before = new BigDecimal(min);
                    BigDecimal after = new BigDecimal(max);
                    return before.compareTo(after);
                }
            });// 排序

            List<FundRedeemModel> redeemList = new ArrayList<>();
            for (int i = 0; i < exceedRateList.size(); i++) {
                FundRate fundRate = exceedRateList.get(i);
                // 排除机构户（大客户）
                if (EqualsUtil.equals(fundRate.getCust_type(), GlobalConstant.CUST_TYPE_ORGANIZATION)) {
                    continue;
                }
                FundRedeemModel redeemModel = new FundRedeemModel();
                redeemModel.setMinDay(fundRate.getMin_hold());
                redeemModel.setMaxDay(fundRate.getMax_hold());
                String ratioStr = fundRate.getRatio();
                if (StringUtil.isEmpty(ratioStr)) {
                    ratioStr = "0";
                }
                BigDecimal ratio = new BigDecimal(ratioStr);
                redeemModel.setFareRatio(MoneyUtils.parseRate(ratio.multiply(GlobalConstant.BIG_DECIMAL_100)));
                redeemList.add(redeemModel);
            }
            result.setFundRedeemList(redeemList);
        }

        result.setSuccess(true);

        return result;
    }

    /**
     * 查询交易记录，过滤掉T0基金
     *
     * @param requestNum    请求行数
     * @param queryFlag     0-不重新统计；1-重新统计； 建议传1
     * @param beginNum      查询起始行号
     * @param sortDirection 返回排序方式
     * @author mifj
     */
    @GetMapping("/record")
    @ResponseBody
    @Loggable
    public BaseResult record(@RequestParam Integer requestNum,
                             @RequestParam Integer queryFlag,
                             @RequestParam Integer beginNum,
                             @RequestParam String sortDirection,
                             HttpServletRequest request) {
        ApplyListResult result = null;
        Long userId = Long.valueOf(RequestUtils.getHeader(request, "userid"));

        result = queryService.queryApplys(userId, requestNum, queryFlag, beginNum, sortDirection, true);
        if (!result.getSuccess() && StringUtil.isEmpty(result.getErrorMessage())) {
            result.setErrorMessage(MessageUtil.getErrorMessage(result.getErrorCode(), null));
        }
        return result;
    }


    /**
     * 资产--基金交易记录
     *
     * @param fundCode  基金代码 非必
     * @param queryType 业务类型, all 全部 onWay 进行中
     * @return
     */
    @GetMapping("/fundRecord")
    @Loggable
    @ResponseBody
    public BaseResult fundRecord(HttpServletRequest request,String fundCode, @NonNull String queryType, String business, Integer requestNum, Integer beginNum, String allotNo) {
        NTradingRecordListResult nTradingRecordListResult = null;
        Long userId = Long.valueOf(RequestUtils.getHeader(request, "userid"));
        try {
            nTradingRecordListResult = applyRecordService.queryFundRecord(fundCode, queryType, userId, beginNum, requestNum, business, allotNo);
        } catch (Exception e) {
            ExceptionUtil.logError(log, "queryApplys - Exception:", e);
        }
        return nTradingRecordListResult;
    }


    /**
     * 查询基金详情总入口
     *
     * @param request
     * @param fundCode 基金代码
     * @return
     * @throws BaseAppException
     * @Author wzh
     */
    @GetMapping("detail")
    @ResponseBody
    @Loggable
    public BaseResult queryFundDetail(HttpServletRequest request, String fundCode) throws BaseAppException {
        FundDetailResult result = null;

        Long userId = null;

        if (!Strings.isNullOrEmpty(request.getHeader("userId"))) {
            userId = Long.valueOf(request.getHeader("userId").trim());
        }

        result = fundDetailService.getFundDetailByFundCode(fundCode, userId);

        if (result == null) {
            result = new FundDetailResult();
            result.setErrorCode(ErrorConstant.ERROR_FUND_NOT_EXIST);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_FUND_NOT_EXIST, fundCode));
            result.setSuccess(false);

            return result;
        }

        result.setInnerCode(null);
        result.setSuccess(true);

        return result;
    }

    /**
     * 基金净值走势图
     *
     * @param fundCode 基金代码
     * @param option   选项
     * @return
     * @throws BaseAppException
     */
    @GetMapping("netValue")
    @ResponseBody
    @Loggable
    public BaseResult getNetValueByFundCode(String fundCode, Integer option) throws BaseAppException {
        BaseResult result = new BaseResult();

        switch (option) {
            case 1:
                result.setResult(fundNetValueBackService.getOneMonthNetValueByFundCode(fundCode));
                break;

            case 2:
                result.setResult(fundNetValueBackService.getThreeMonthNetValueByFundCode(fundCode));
                break;

            case 3:
                result.setResult(fundNetValueBackService.getSixMonthNetValueByFundCode(fundCode));
                break;

            case 4:
                result.setResult(fundNetValueBackService.getOneYearNetValueByFundCode(fundCode));
                break;
        }

        return result;
    }

    /**
     * 获取基金历史净值  查看更多
     *
     * @param fundCode
     * @param pageable
     * @return
     * @throws BaseAppException
     */
    @GetMapping("get_history_net_values")
    @ResponseBody
    @Loggable
    public BaseResult getHistoryNetValues(String fundCode, Pageable pageable) throws BaseAppException {
        BaseResult result = new BaseResult();

        result.setResult(fundNetValueBackService.queryPages(pageable, fundCode));

        return result;
    }

    /**
     * 获取图表中用户买入日期
     *
     * @param request
     * @param fundCode
     * @return
     * @throws BaseAppException
     */
    @GetMapping("trading")
    @ResponseBody
    @Loggable
    public BaseResult getTradingDay(HttpServletRequest request, String fundCode) throws BaseAppException {
        BaseResult result = new BaseResult();
        Long userId = null;

        if (!Strings.isNullOrEmpty(request.getHeader("userId"))) {
            userId = Long.valueOf(request.getHeader("userId").trim());
        }

        if (userId == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_NO_USER_FIND);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_NO_USER_FIND));

            return result;
        }

        result.setResult(fundNetValueBackService.getTradeDay(fundCode, userId));

        return result;
    }

    /**
     * 获取图表中用户买入日期
     *
     * @param request
     * @param fundCode
     * @return
     * @throws BaseAppException
     */
    @GetMapping("sellTrading")
    @ResponseBody
    @Loggable
    public BaseResult getSellTradingDay(HttpServletRequest request, String fundCode) throws BaseAppException {
        BaseResult result = new BaseResult();
        Long userId = null;

        if (!Strings.isNullOrEmpty(request.getHeader("userId"))) {
            userId = Long.valueOf(request.getHeader("userId").trim());
        }

        if (userId == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_NO_USER_FIND);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_NO_USER_FIND));

            return result;
        }

        result.setResult(tradeOrderService.getSellConfirmDates(fundCode, userId));

        return result;
    }

    /**
     * 获取货币基金历史七日年化 查看更多
     *
     * @param fundCode
     * @param pageable
     * @return
     * @throws BaseAppException
     */
    @GetMapping("get_history_seven_day_annualized")
    @ResponseBody
    @Loggable
    public BaseResult getHistorySevenDayAnnualized(String fundCode, Pageable pageable) throws BaseAppException {
        BaseResult result = new BaseResult();

        result.setResult(fundNetValueBackService.queryMMPages(pageable, fundCode));

        return result;
    }

    /**
     * 基金-买入，重定向至瑞富宝买入逻辑
     * 对风险评测进行了修改
     * 不知道机构是否调用
     * @param request
     * @param fundCode
     * @return
     */
    @GetMapping("goBuy")
    @ResponseBody
    @Loggable
    public CheckResult goBuy(HttpServletRequest request, @RequestParam String fundCode) {
        Long userId = Long.valueOf(RequestUtils.getHeader(request, "userid"));
        CheckResult result = new CheckResult();
        User userEntity = userService.getUser(userId);
        if (userEntity == null) {
            result.setSuccess(false);
            result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
            result.setErrorCode(ErrorConstant.ERROR_NO_USER_FIND);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_NO_USER_FIND));
            return result;
        }
        result.setSuccess(true);
        String externalClientId = userEntity.getExternalClientId();
        if (StringUtil.isEmpty(externalClientId)) {
            // 未开户
            result.setStatus(1);
            return result;
        } else {
            // 获取用户银行卡
            BaseListResult listResult = queryService.queryAccountBanks("", userEntity.getExternalClientId(), "",
                GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1");
            if (!listResult.getSuccess()) {
                result.setSuccess(false);
                result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                result.setErrorCode(ErrorConstant.ERROR_NO_BANK_CARD_FIND);
                result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_NO_BANK_CARD_FIND));
                return result;
            }
            List<BankModel> banks = ((BankListResult) listResult).getBanks();
            if (banks == null || banks.size() == 0) {
                // 未开户
                result.setStatus(1);
                return result;
            } else {
                // 判断是否开户
                boolean isOpen = false;
                for (BankModel bankModel : banks) {
                    if (!StringUtil.isEmpty(bankModel.getCapitalMode()) && !bankModel.getCapitalMode().equals(GlobalConstant.CAPITAL_MODE_COUNTER)) {
                        isOpen = true;
                        break;
                    }
                }
                if (!isOpen) {
                    // 未开户
                    result.setStatus(1);
                    return result;
                } else {
                    //判断是否已在私募入口做过风险测评，如果已做过，则传入之前的风险测评结果
                    PaperInfoTestResult privateResult = paperInfoService.getUserPaperInfoTestResult(userId, "",null);

                    if (privateResult.isHave_tested()) {
                        String expireDate = privateResult.getExpire_date();
                        Date now = new Date();
                        Date expire = DateUtil.parse(expireDate);
                        if (now.after(expire)) {
                            //风险评测过期
                            result.setStatus(3);
                            return result;
                        } else {
                            //查询个人的风险评测等级
                            result.setStatus(0);
                            BaseResult baseResult = null;
                            try {
                                baseResult = paymentService.getPayMethods(userId);
                            } catch (BaseAppException e) {
                                result.setSuccess(false);
                                result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                                result.setErrorCode(ErrorConstant.ERROR_NO_BANK_CARD_FIND);
                                result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_NO_BANK_CARD_FIND));
                                return result;
                            }
                            if (baseResult.getResult() == null) {
                                result.setSuccess(false);
                                result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                                result.setErrorCode(ErrorConstant.ERROR_NO_BANK_CARD_FIND);
                                result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_NO_BANK_CARD_FIND));
                                return result;
                            } else {
                                ShareTypeModel shareTypeModel = queryService.getShareType(fundCode);
                                if (shareTypeModel == null || StringUtil.isEmpty(shareTypeModel.getShareType())) {
                                    result.setSuccess(false);
                                    result.setErrorCode(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND);
                                    result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
                                    result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND, null));
                                    return result;
                                }
                                String shareType = shareTypeModel.getShareType();
                                String custType = userEntity.getIsOrg() ? GlobalConstant.CUST_TYPE_ORGANIZATION : GlobalConstant.CUST_TYPE_PERSONAL;
                                TradeLimitListResult limitListResult = queryService.queryTradeLimits(GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1", fundCode, shareType,
                                    GlobalConstant.CAPITAL_MODE_EPAY, "022", custType);
                                if (limitListResult.getSuccess() == false) {
                                    result.setSuccess(false);
                                    result.setErrorCode(limitListResult.getErrorCode());
                                    result.setErrorType(limitListResult.getErrorType());
                                    result.setErrorMessage(MessageUtil.getErrorMessage(limitListResult.getErrorCode(), null));
                                    return result;
                                }
                                Map<String,String> userInv = Maps.newHashMap();
                                userInv.put("userRisk",privateResult.getInvest_risk_tolerance());
                                userInv.put("userRiskDesc",privateResult.getInvest_risk_tolerance_desc());
                                Map<String, Object> resultMap = Maps.newHashMap();
                                resultMap.put("payWay", baseResult.getResult());
                                resultMap.put("limits", limitListResult.getLimits());
                                resultMap.put("userInv", userInv);
                                result.setResult(resultMap);
                                return result;
                            }
                        }
                    } else {
                        //未做风险评测
                        result.setStatus(2);
                        return result;
                    }
                }
            }
        }
    }

    /**
     * 基金--确认买入
     *
     * @param request
     * @return
     */
    @PostMapping("sureBuy")
    @ResponseBody
    @Loggable
    public BaseResult sureBuy(RedirectAttributes attr, HttpServletRequest request, @Validated BuyVo buyVo) {
        BaseResult result = null;
        Long userId = Long.valueOf(RequestUtils.getHeader(request, "userid"));
        String chanelCode = RequestUtils.getHeader(request, "channelCode");
        buyVo.setUserId(userId);
        buyVo.setChannelId(chanelCode);
        buyVo.setMoneyType(GlobalConstant.MONEY_TYPE_RMB);
        // 验证输入
        result = tradeValidation.validateBuy(buyVo);
        if (result != null) {
            return result;
        }
        // 调用接口
        result = tradeService.buy(buyVo);
        BaseResultUtil.parseErrMsg(result);
        return result;
    }

    /**
     * 基金--预估费用
     *
     * @param balance
     * @param fundCode
     * @return
     * @throws BaseAppException
     */
    @GetMapping("estimateCost")
    @ResponseBody
    @Loggable
    public FundTradeRatio estimateCost(HttpServletRequest request, @RequestParam BigDecimal balance, @RequestParam String fundCode) {
        Long userId = Long.valueOf(RequestUtils.getHeader(request, "userid"));
        User userEntity = userService.getUser(userId);
        String custType = GlobalConstant.CUST_TYPE_PERSONAL;
        if (userEntity.getIsOrg()) {
            custType = GlobalConstant.CUST_TYPE_ORGANIZATION;
        }
        return queryService.getApplyFundRate(fundCode, balance, custType);
    }

    /**
     * 基金--定投
     * 对风险评测进行了修改
     * 不知道机构是否调用
     * @param fundCode
     * @return
     */
    @GetMapping("goCircleBuy")
    @ResponseBody
    @Loggable
    public CheckResult goCircleBuy(HttpServletRequest request, @RequestParam String fundCode) {
        Long userId = Long.valueOf(RequestUtils.getHeader(request, "userid"));
        Map<String, Object> returnMap = Maps.newHashMap();
        CheckResult result = new CheckResult();

        User user = userService.getUser(userId);
        String externalClientId = user.getExternalClientId();
        result.setSuccess(true);
        if (StringUtil.isEmpty(externalClientId)) {
            // 未开户
            result.setStatus(1);
            return result;
        }
        List<UserBank> userBanks = bankService.getListByUserId(userId);
        if (userBanks == null || userBanks.size() == 0) {
            // 未开户
            result.setStatus(1);
            return result;
        }
        boolean isOpen = false;
        for (UserBank bankModel : userBanks) {
            if (!StringUtil.isEmpty(bankModel.getCapitalMode()) && !bankModel.getCapitalMode().equals(GlobalConstant.CAPITAL_MODE_COUNTER)) {
                isOpen = true;
                break;
            }
        }
        if (!isOpen) {
            // 未开户
            result.setStatus(1);
            return result;
        }
        //判断是否已在私募入口做过风险测评，如果已做过，则传入之前的风险测评结果
        PaperInfoTestResult privateResult = paperInfoService.getUserPaperInfoTestResult(userId, "",null);
        if (!privateResult.isHave_tested()) {
            //未做风险评测
            result.setStatus(2);
            return result;
        }
        String expireDate = privateResult.getExpire_date();
        Date now = new Date();
        Date expire = DateUtil.parse(expireDate);
        if (now.after(expire)) {
            //风险评测过期
            result.setStatus(3);
            return result;
        }
        result.setStatus(0);

        ShareTypeModel shareTypeModel = queryService.getShareType(fundCode);
        if (shareTypeModel == null || StringUtil.isEmpty(shareTypeModel.getShareType())) {
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND);
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND, null));
            return result;
        }
        String shareType = shareTypeModel.getShareType();
        String custType = user.getIsOrg() ? GlobalConstant.CUST_TYPE_ORGANIZATION : GlobalConstant.CUST_TYPE_PERSONAL;
        TradeLimitListResult resultLimit = queryService.queryTradeLimits(GlobalConstant.MAX_REQUEST_NUM, 1, 1, "1", fundCode, shareType,
            GlobalConstant.CAPITAL_MODE_EPAY, "039", custType);
        if (resultLimit.getSuccess() == false) {
            result.setSuccess(false);
            result.setErrorCode(resultLimit.getErrorCode());
            result.setErrorMessage(MessageUtil.getErrorMessage(resultLimit.getErrorCode(), null));
            return result;
        }
        List<BankModel> banks = new ArrayList<>(userBanks.size());
        userBanks.forEach(bank -> {
            BankModel bankModel = new BankModel();
            bankModel.setBranchBank(bank.getBranchbank() == null ? "" : bank.getBranchbank());
            bankModel.setBranchBankName(bank.getBankBranchName() == null ? "" : bank.getBankBranchName());
            bankModel.setBankName(bank.getBankName());
            bankModel.setBankCode(bank.getBankCode());
            bankModel.setUserBankNo(bank.getUserBankNo());
            bankModel.setCapitalMode(bank.getCapitalMode());
            bankModel.setTradeAccount(bank.getExternalTradeAccount());
            banks.add(bankModel);
        });
        Map<String, String> userInv = Maps.newHashMap();
        userInv.put("userRisk", privateResult.getInvest_risk_tolerance());
        userInv.put("userRiskDesc", privateResult.getInvest_risk_tolerance_desc());
        returnMap.put("limits", resultLimit.getLimits());
        returnMap.put("banks", banks);
        returnMap.put("userInv", userInv);
        result.setResult(returnMap);
        return result;
    }

    /**
     * 基金--详情--确定定投
     *
     * @param request
     * @param tradePassword      交易密码
     * @param applyNo            前端根据当前时间自动生成，格式：yyyyMMddHHmmssSSS
     * @param bankAccount        银行账号
     * @param fundName           基金名称
     * @param fundCode           基金代码
     * @param balance            定投金额
     * @param protocolPeriodUnit 扣款周期
     * @param protocolFixDay     扣款日期
     * @return
     */
    @PostMapping("sureCircleBuy")
    @ResponseBody
    @Loggable
    public BaseResult sureCircleBuy(HttpServletRequest request, @RequestParam String tradePassword, @RequestParam String applyNo,
                                    @RequestParam String bankAccount, @RequestParam String fundName, @RequestParam String fundCode,
                                    @RequestParam BigDecimal balance, @RequestParam String protocolPeriodUnit, @RequestParam Long protocolFixDay, @RequestParam String capitalMode) {
        Long userId = Long.valueOf(RequestUtils.getHeader(request, "userid"));
        String chanelCode = RequestUtils.getHeader(request, "channelCode");
        BaseResult result = new BaseResult();
        // 机构用户不能定投
        User user = userService.getUser(userId);
        if (user.getIsOrg()) {
            result.setSuccess(false)
                .setErrorCode(ErrorConst.COMMON_USER_PERMISSION_ONLY)
                .setErrorMessage(MessageUtil.getErrorMsg(ErrorConst.COMMON_USER_PERMISSION_ONLY));
            return result;
        }
        BaseResult validResult = tradeValidation.baseValidate(bankAccount, capitalMode, fundName, fundCode, tradePassword);
        if (validResult != null) {
            return validResult;
        }
        // 如果两个数一样则返回0，如果第一个数比第二个数大则返回1，反之返回-1
        if (MoneyUtils.compareTo(balance, 0) != 1) {
            result.setErrorCode(ErrorConstant.ERROR_FIELD_NO_FIND);
            Map<String, String> map = new HashMap<>();
            map.put(ErrorConstant.PLACEHOLDER_FIELD_NO_FIND_FIELD, "定投金额");
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_FIELD_NO_FIND, map));
            return result;
        }

        // 扣款周期不能为空
        if (StringUtil.isEmpty(protocolPeriodUnit)) {
            result.setErrorCode(ErrorConstant.ERROR_FIELD_NO_FIND);
            Map<String, String> map = new HashMap<>();
            map.put(ErrorConstant.PLACEHOLDER_FIELD_NO_FIND_FIELD, "扣款周期");
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_FIELD_NO_FIND, map));
            return result;
        }

        // 扣款日期要在1~31之间
        if (protocolFixDay.compareTo(0l) < 0) {
            result.setErrorCode(ErrorConstant.ERROR_INVALID_DATE);
            Map<String, String> map = new HashMap<>();
            map.put(ErrorConstant.PLACEHOLDER_FIELD_NO_FIND_FIELD, "扣款日期");
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_FIELD_NO_FIND, map));
            return result;
        }

        // 扣款日期不能是当天，也不能是29~31
        Calendar now = Calendar.getInstance();
        now.setTime(new Date());
        if (protocolFixDay.compareTo(28l) > 0) {
            result.setErrorCode(ErrorConstant.ERROR_NOT_SUPPORT_DAY);
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_NOT_SUPPORT_DAY, null));
            return result;
        }
        // 验证是否重复提交, 5分钟过期
        applyNo = applyNo + userId;
        String applyKey = CacheUtil.getKey(GlobalConstant.REDIS_KEY_APPLY_SELL, applyNo);
        if (!StringUtil.isEmpty(stringRedisTemplate.opsForValue().get(applyKey))) {
            result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
            result.setErrorCode(ErrorConstant.ERROR_DUPLICATE_APPLY);
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_DUPLICATE_APPLY, null));
            return result;
        }
        stringRedisTemplate.opsForValue().set(applyKey, applyNo, GlobalConstant.APPLY_EXPIRED_HOURS_DEFAULT, TimeUnit.HOURS);
        //基金购买前界面已经提示风险等级不符合，购买时不再判断
        /*NewsModel fundRiskLevel = queryService.getRiskLevel(fundCode);
        PaperInfoTestResult testResult = paperInfoService.getUserPaperInfoTestResult(userId, "");
        Integer investRiskLevel = 0;
        if (!StringUtil.isEmpty(testResult.getInvest_risk_tolerance())) {
            investRiskLevel = Integer.parseInt(testResult.getInvest_risk_tolerance());
        }
        // 基金的风险等级大于用户的投资风险等级
        *//*进取型5,成长型4,平衡型3,稳健型2,保守型1
          高风险5,中高风险4,中风险3,中低风险2,低风险1*//*
        if (investRiskLevel < fundRiskLevel.getRiskLevel()) {
            result.setSuccess(false);
            result.setErrorType(GlobalConstant.ERROR_TYPE_BUSINESS);
            result.setErrorCode(ErrorConstant.ERROR_RISK_LEVEL);
            result.setErrorMessage(MessageUtil.getErrorMessage(result.getErrorCode(), null));
            return result;
        }*/
        // 获取份额类别
        ShareTypeModel shareTypeModel = queryService.getShareType(fundCode);
        if (shareTypeModel == null || StringUtil.isEmpty(shareTypeModel.getShareType())) {
            result.setSuccess(false);
            result.setErrorType(GlobalConstant.ERROR_TYPE_APPLICATION);
            result.setErrorCode(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND);
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_NO_SHARE_TYPE_FIND, null));
            return result;
        }
        String shareType = shareTypeModel.getShareType(); // 份额类别
        // 调用接口
        result = tradeService.fixReal(applyNo, tradePassword, protocolFixDay, shareType, bankAccount, fundName,
            protocolPeriodUnit, userId, balance, fundCode, capitalMode, chanelCode, GlobalConstant.FIX_MODEL_NORMAL,
            null, null);
        if (!result.getSuccess() && StringUtil.isEmpty(result.getErrorMessage())) {
            result.setErrorMessage(MessageUtil.getErrorMessage(result.getErrorCode(), null));
        }
        return result;
    }

    /**
     * 基金--撤单
     *
     * @param attr
     * @param allotNo       源交易申请编号
     * @param tradePassword 交易密码
     * @param applyNo       客户端自动生成，格式：yyyyMMddHHmmssSSS
     * @return
     */
    @PostMapping("undo")
    @Loggable
    public String undo(RedirectAttributes attr, @RequestParam String allotNo, @RequestParam String tradePassword, @RequestParam String applyNo) {
        attr.addAttribute("allotNo", allotNo);
        attr.addAttribute("tradePassword", tradePassword);
        attr.addAttribute("applyNo", applyNo);
        return "forward:/h5/ruifubao/undo";
    }

    /**
     * 基金分红交易记录
     */
    @GetMapping("/dividend/apply")
    @ResponseBody
    @Loggable
    public BaseResult dividendApply(@RequestParam Integer requestNum,
                                    @RequestParam Integer queryFlag,
                                    @RequestParam Integer beginNum,
                                    @RequestParam String sortDirection, HttpServletRequest request) {
        Long userId = Long.valueOf(RequestUtils.getHeader(request, "userid"));
        String taSerialId = null;
        DividendApplyResult result = dividendApplyQuery.queryNormalDividendApplys(userId, requestNum, queryFlag, beginNum,
            sortDirection, taSerialId);
        if (!result.getSuccess() && StringUtil.isEmpty(result.getErrorMessage())) {
            result.setErrorMessage(MessageUtil.getErrorMessage(result.getErrorCode(), null));
        }
        return result;
    }


    /**
     * 查询基金基本信息
     *
     * @param request
     * @param keyword
     * @throws Exception
     */
    @GetMapping("/search")
    @ResponseBody
    @Loggable
    public BaseResult queryFundInfo(HttpServletRequest request, @RequestParam String keyword) {
        BaseResult result;
        Long userId = Long.valueOf(RequestUtils.getHeader(request, "userid"));
        try {
            // 查询基金
            result = fundInfoService.query(keyword, userId);
        } catch (BaseException exception) {
            result = new FundInfoListResult();
            result.setSuccess(false);
            Integer errorCode = exception.getCode();
            result.setErrorCode(errorCode);
            if (StringUtil.isEmpty(result.getErrorMessage())) {
                String errorMessage = MessageUtil.getErrorMessage(errorCode, null);
                result.setErrorMessage(errorMessage);
            }
        } catch (Exception e) {
            ExceptionUtil.logError(log, "queryFundInfo - Exception:", e);
            result = new FundInfoListResult();
            result.setSuccess(false);
            result.setErrorCode(ErrorConstant.ERROR_SYS_EXCEPTION);
            result.setErrorMessage(MessageUtil.getErrorMessage(ErrorConstant.ERROR_SYS_EXCEPTION, null));
        }
        return result;
    }
}
